﻿using System;
using System.Text;
using System.Collections.Generic;
using System.Linq;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using ScrumDashboardMvc.Controllers;
using ScrumDashboard.Library.Data;
using StructureMap;
using System.Web.Mvc;
using Moq;
using ScrumDashboard.Library.Models;

namespace ScrumDashboardMvc.Tests
{
    [TestClass]
    public class TestDashboardController
    {
        [TestMethod]
        public void Should_Add_Product_Backlog_To_TeamSprint()
        {
            var mockRepo = new Mock<IRepository>();
            var mockProj = new Mock<IProjectHandler>();
            var mockTeam = new Mock<ITeamSprintHandler>();

            mockRepo.Setup(f => f.GetHandler<IProjectHandler>()).Returns(mockProj.Object);
            mockRepo.Setup(f => f.GetHandler<ITeamSprintHandler>()).Returns(mockTeam.Object);
            mockTeam.Setup(t => t.GetTeamSprint(88)).Returns(new TeamSprint(){IterationPath="Iteration\\Path\\Team"});

            DashboardController d = new DashboardController(mockRepo.Object);
            d.AddProductBacklogItems(77, 88, new int[] { 99 });

            mockProj.Verify(p => p.SetIterationPath(new[] { 99 }, "Iteration\\Path\\Team"));
        }

        [TestMethod]
        public void Should_Add_Product_Backlog_To_Sprint()
        {
            var mockRepo = new Mock<IRepository>();
            var mockProj = new Mock<IProjectHandler>();
            var mockTeam = new Mock<ISprintHandler>();

            mockRepo.Setup(f => f.GetHandler<IProjectHandler>()).Returns(mockProj.Object);
            mockRepo.Setup(f => f.GetHandler<ISprintHandler>()).Returns(mockTeam.Object);
            mockTeam.Setup(t => t.GetSprint(77)).Returns(new Sprint() { IterationPath = "Iteration\\Path" });

            DashboardController d = new DashboardController(mockRepo.Object);
            d.AddProductBacklogItems(77, null, new int[] { 99 });

            mockProj.Verify(p => p.SetIterationPath(new[] { 99 }, "Iteration\\Path"));
        }

        [TestMethod]
        public void Add_Product_Backlog_Should_Handle_NullValues()
        {
            var mockRepo = new Mock<IRepository>();
            var mockProj = new Mock<IProjectHandler>();
            var mockTeam = new Mock<ISprintHandler>();

            mockRepo.Setup(f => f.GetHandler<IProjectHandler>()).Returns(mockProj.Object);
            mockRepo.Setup(f => f.GetHandler<ISprintHandler>()).Returns(mockTeam.Object);
            mockTeam.Setup(t => t.GetSprint(77)).Returns(new Sprint() { IterationPath = "Iteration\\Path" });

            DashboardController d = new DashboardController(mockRepo.Object);
            d.AddProductBacklogItems(77, null, new int[] {});

            mockProj.Verify(p => p.SetIterationPath(It.IsAny<int[]>(), It.IsAny<string>()), Times.Never());
        }

        [TestMethod]
        public void Import_Work_Items_To_Backlog()
        {
            var mockRepo = new Mock<IRepository>(MockBehavior.Strict);
            var mockBacklog = new Mock<IBacklogItemHandler>();
            mockRepo.Setup(f => f.GetHandler<IBacklogItemHandler>()).Returns(mockBacklog.Object);
            mockBacklog.Setup(t => t.ImportWorkItemsToBacklog(1, BacklogItemType.AcceptanceTest, new int[] { 2 })).Returns(new BacklogItem[] { new AcceptanceTest() }).Verifiable();

            DashboardController d = new DashboardController(mockRepo.Object);
            d.ImportTasks(1, "AcceptanceTest", new int[] { 2 });

            mockBacklog.Verify();
        }

        [TestMethod]
        public void Import_Work_Items_To_Backlog_Should_Deny_Invalid_Type()
        {
            var mockRepo = new Mock<IRepository>(MockBehavior.Strict);
            var mockBacklog = new Mock<IBacklogItemHandler>();
            mockRepo.Setup(f => f.GetHandler<IBacklogItemHandler>()).Returns(mockBacklog.Object);

            DashboardController d = new DashboardController(mockRepo.Object);

            try
            {
                d.ImportTasks(1, "KalleKule", new int[] { 2 });
                Assert.Fail("Importing tasks with invalid type should throw");
            }
            catch (ArgumentException)
            {
            }

            mockBacklog.Verify(t => t.ImportWorkItemsToBacklog(It.IsAny<int>(), It.IsAny<BacklogItemType>(), It.IsAny<int[]>()),Times.Never());
        }

        [TestMethod]
        public void Import_Work_Items_To_Backlog_Should_Handle_NullValues()
        {
            var mockRepo = new Mock<IRepository>(MockBehavior.Strict);
            var mockBacklog = new Mock<IBacklogItemHandler>();
            mockRepo.Setup(f => f.GetHandler<IBacklogItemHandler>()).Returns(mockBacklog.Object);

            DashboardController d = new DashboardController(mockRepo.Object);
            d.ImportTasks(1, "AcceptanceTest", null);

            mockBacklog.Verify(t => t.ImportWorkItemsToBacklog(It.IsAny<int>(), It.IsAny<BacklogItemType>(), It.IsAny<int[]>()), Times.Never());
        }
    }
}
